#include "block.h"
#include "BufferManager.h"
#include "UserCommand.h"
#include "CatalogManager.h"
#include "IndexManager.h"
#include "recordManager.h"
#include <stdio.h>
#include <vector>
#include <string>
#include <sstream>

using namespace std;

#define BLOCKSIZE 4096

Record::Record(shared_ptr<BufferManager> buffer)
{
	this->buffer = buffer;
}

Record::~Record(){}

void Record::createTable(string tableName)
{
	Block block;
	string tbName = tableName + ".tb";
	int size = tbName.size();

	buffer->clearBlock(tbName, 0);
	block.writeChar(tableName, 0);
	block.writeInt(size, 0);
	block.writeInt(size + 4, 0);
	buffer->writeBlock(tbName, 0, block);
	buffer->clearBlock(tbName, 1);
}

vector<string> Record::select(string tableName, Attribute attr, vector<Attribute> attribute)
{
	Block recordBlock;
	string tbName = tableName + ".tb";
	int attrPos;
	int blockNum;
	int attrPosSize(0);
	int rowDataSize(0);
	vector<string> resultStr;
	
	int blockRecordNum = getBlockRecordNum(attribute);
	
	for(int i = 0; i < attribute.size(); i++)
	{
		if(attribute[i].attrName == attr.attrName)
		{
			attrPos = i;
			break;
		}
	}
	
	attrPosSize = getAttrPosSize(attrPos, attribute);
	rowDataSize = getRowDataSize(attribute);
	recordBlock = buffer->readBlock(tbName, 0);
	int size = tableName.size();
	int totalRecordCount = recordBlock.readInt(size + 4);

	for(int i = 0; i < totalRecordCount; i++)
	{
		blockNum = getBlockNum(attribute, i);
		recordBlock = buffer->readBlock(tbName, blockNum);
		char isWritten = recordBlock.readByte((i%blockRecordNum) * rowDataSize);
		if(isWritten == '1')
		{
			if(attribute[attrPos].attrType < 0)
			{
				int resInt = recordBlock.readInt((i%blockRecordNum)*rowDataSize + attrPosSize);
				stringstream ss;
				ss << resInt;
				string str = ss.str();
				resultStr.push_back(str);
			}
			else if(attribute[attrPos].attrType == 0)
			{
				float resFloat = recordBlock.readFloat((i%blockRecordNum)*rowDataSize + attrPosSize);
				stringstream ss;
				ss << resFloat;
				string str = ss.str();
				resultStr.push_back(str);
			}
			else
			{
				int length = attribute[attrPos].attrType;
				string resString = recordBlock.readChar((i%blockRecordNum)*rowDataSize + attrPosSize, length);
				resultStr.push_back(resString);
			}
		}
	}

	return resultStr;

}

vector<vector<string>> Record::select(string tableName, CUserCommand userCommand, vector<Attribute> attribute)
{
	Block recordBlock;
	string tbName = tableName + ".tb";
	int rowDataSize(0);
	vector<vector<string>> data;
	vector<string> resultStr/* (NULL) */;

	rowDataSize = getRowDataSize(attribute);
	int blockRecordNum = getBlockRecordNum(attribute);
	recordBlock = buffer->readBlock(tbName, 0);
	int size = tableName.size();
	int recordcount = recordBlock.readInt(size + 4);
	int maxBlockNum = getBlockNum(attribute, recordcount - 1);
	vector<string> selectColStr = userCommand.GetSelectCol();
	vector<int> selectCol;
	
	for(int i = 0; i < attribute.size(); i++)
		for(int j = 0; j < selectColStr.size(); j++)
		{
			if(attribute[i].attrName == selectColStr[j])		
				selectCol.push_back(i);
		}

	for(int k = 0; k < maxBlockNum; k++) 
	{
		recordBlock = buffer->readBlock(tbName, k);
		if(k == maxBlockNum - 1)
		{	
			for(int i = (maxBlockNum-1) * blockRecordNum; i < recordcount; i++)
			{
				char isWritten = recordBlock.readByte((i%blockRecordNum) * rowDataSize);
				if(isWritten == '1')
				{
					if(selectColStr[0] == "*")
					{
						for(int j = 0; j < attribute.size(); j++)
						{
							if(attribute[j].attrType < 0)
							{
								int attrPosSize = getAttrPosSize(j, attribute);
								int resInt = recordBlock.readInt((i%blockRecordNum)*rowDataSize + attrPosSize);
								stringstream ss;
								ss << resInt;
								string str = ss.str();
								resultStr.push_back(str);
							}
							else if(attribute[j].attrType == 0)
							{
								int attrPosSize = getAttrPosSize(j, attribute);
								float resFloat = recordBlock.readFloat((i%blockRecordNum)*rowDataSize + attrPosSize);
								stringstream ss;
								ss << resFloat;
								string str = ss.str();
								resultStr.push_back(str);
							}
							else
							{
								int length = attribute[j].attrType;
								int attrPosSize = getAttrPosSize(j, attribute);
								string resString = recordBlock.readChar((i%blockRecordNum)*rowDataSize + attrPosSize, length);
								resultStr.push_back(resString);
							}
						}

						data.push_back(resultStr);
					}
					else
					{
						for(int j = 0; j < selectCol.size(); j++)
						{
							if(attribute[selectCol[j]].attrType < 0)
							{
								int attrPosSize = getAttrPosSize(selectCol[j], attribute);
								int resInt = recordBlock.readInt((i%blockRecordNum)*rowDataSize + attrPosSize);
								stringstream ss;
								ss << resInt;
								string str = ss.str();
								resultStr.push_back(str);
							}
							else if(attribute[selectCol[j]].attrType == 0)
							{
								int attrPosSize = getAttrPosSize(selectCol[j], attribute);
								float resFloat = recordBlock.readFloat((i%blockRecordNum)*rowDataSize + attrPosSize);
								stringstream ss;
								ss << resFloat;
								string str = ss.str();
								resultStr.push_back(str);
							}
							else
							{
								int length = attribute[selectCol[j]].attrType;
								int attrPosSize = getAttrPosSize(selectCol[j], attribute);
								string resString = recordBlock.readChar((i%blockRecordNum)*rowDataSize + attrPosSize, length);
								resultStr.push_back(resString);
							}
						}

						data.push_back(resultStr);
					}
				}
			}
		}
		else
		{
			for(int i = k * blockRecordNum; i < (k+1) * blockRecordNum; i++)
			{
				char isWritten = recordBlock.readByte((i%blockRecordNum) * rowDataSize);
				if(isWritten == '1')
				{
					if(selectColStr[0] == "*")
					{
						for(int j = 0; j < attribute.size(); j++)
						{
							if(attribute[j].attrType < 0)
							{
								int attrPosSize = getAttrPosSize(j, attribute);
								int resInt = recordBlock.readInt((i%blockRecordNum)*rowDataSize + attrPosSize);
								stringstream ss;
								ss << resInt;
								string str = ss.str();
								resultStr.push_back(str);
							}
							else if(attribute[j].attrType == 0)
							{
								int attrPosSize = getAttrPosSize(j, attribute);
								float resFloat = recordBlock.readFloat((i%blockRecordNum)*rowDataSize + attrPosSize);
								stringstream ss;
								ss << resFloat;
								string str = ss.str();
								resultStr.push_back(str);
							}
							else
							{
								int length = attribute[j].attrType;
								int attrPosSize = getAttrPosSize(j, attribute);
								string resString = recordBlock.readChar((i%blockRecordNum)*rowDataSize + attrPosSize, length);
								resultStr.push_back(resString);
							}
						}

						data.push_back(resultStr);
					}
					else
					{
						for(int j = 0; j < selectCol.size(); j++)
						{
							if(attribute[selectCol[j]].attrType < 0)
							{
								int attrPosSize = getAttrPosSize(selectCol[j], attribute);
								int resInt = recordBlock.readInt((i%blockRecordNum)*rowDataSize + attrPosSize);
								stringstream ss;
								ss << resInt;
								string str = ss.str();
								resultStr.push_back(str);
							}
							else if(attribute[selectCol[j]].attrType == 0)
							{
								int attrPosSize = getAttrPosSize(selectCol[j], attribute);
								float resFloat = recordBlock.readFloat((i%blockRecordNum)*rowDataSize + attrPosSize);
								stringstream ss;
								ss << resFloat;
								string str = ss.str();
								resultStr.push_back(str);
							}
							else
							{
								int length = attribute[selectCol[j]].attrType;
								int attrPosSize = getAttrPosSize(selectCol[j], attribute);
								string resString = recordBlock.readChar((i%blockRecordNum)*rowDataSize + attrPosSize, length);
								resultStr.push_back(resString);
							}
						}

						data.push_back(resultStr);
					}
				}
			}
		}
	}

	return data;
}

vector<vector<string>> Record::select(string tableName, CUserCommand userCommand, vector<Condition> condition, vector<Attribute> attribute)
{
	Block recordBlock;
	string tbName = tableName + ".tb";
	recordBlock = buffer->readBlock(tbName, 0);
	int size = tableName.size();
	int totalRecordCount = recordBlock.readInt(size+4);
	int conSize = condition.size();
	int attrPos;
	bool flag = 0;
	vector<int> resultRowNum;
	vector<vector<string>> data;
	vector<string> resultStr(NULL);
	vector<string> selectCol = userCommand.GetSelectCol();
	int blockRecordNum = getBlockRecordNum(attribute);
	int rowDataSize = getRowDataSize(attribute);
	vector<int> selectColNum;

	for(int i = 0; i < totalRecordCount; i++)
	{
		for(int j = 0; j < conSize; j++)
		{
			for(int k = 0; k < attribute.size(); k++)
			{
				if(attribute[k].attrName == condition[j].conCol)
					attrPos = k;
				int attrPosSize = getAttrPosSize(k, attribute);
				int blockNum = getBlockNum(attribute, i);
				recordBlock = buffer->readBlock(tbName, blockNum);
				if(attribute[attrPos].attrType < 0)
				{
					int recordValue = recordBlock.readInt((i%blockRecordNum) * rowDataSize + attrPosSize);
					stringstream ss;
					int compareValue;
					ss >> condition[k].conValue;
					ss << compareValue;
					switch(condition[k].conOperator)
					{
						case COMP_EQUAL:		// =
							if(recordValue == compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_NOT_EQUAL:	// <>
							if(recordValue != compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_LESS:			// <
							if(recordValue < compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_LARGE:		// >
							if(recordValue > compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_LESS_EQUAL:	// <=
							if(recordValue <= compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_LARGE_EQUAL:	// >=
							if(recordValue >= compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
					}
				}
				if(attribute[attrPos].attrType == 0)
				{
					float recordValue = recordBlock.readFloat((i%blockRecordNum) * rowDataSize + attrPosSize);
					stringstream ss;
					float compareValue;
					ss >> condition[k].conValue;
					ss << compareValue;
					switch(condition[k].conOperator)
					{
						case COMP_EQUAL:		// =
							if(recordValue == compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_NOT_EQUAL:	// <>
							if(recordValue != compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_LESS:			// <
							if(recordValue < compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_LARGE:		// >
							if(recordValue > compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_LESS_EQUAL:	// <=
							if(recordValue <= compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_LARGE_EQUAL:	// >=
							if(recordValue >= compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
					}
				}
				else
				{
					int length = attribute[attrPos].attrType;
					string recordValue = recordBlock.readChar((i%blockRecordNum) * rowDataSize + attrPosSize, length);
					stringstream ss;
					string compareValue = condition[k].conValue;
					switch(condition[k].conOperator)
					{
						case COMP_EQUAL:		// =
							if(recordValue == compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_NOT_EQUAL:	// <>
							if(recordValue != compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_LESS:			// <
							if(recordValue < compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_LARGE:		// >
							if(recordValue > compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_LESS_EQUAL:	// <=
							if(recordValue <= compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_LARGE_EQUAL:	// >=
							if(recordValue >= compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
					}
				}
			}
		}
		if(flag == 1)
			resultRowNum.push_back(i);
	}
	if(selectCol[0] == "*")
	{
		for(int i = 0; i < resultRowNum.size(); i++)
		{
			int blockNum = getBlockNum(attribute, resultRowNum[i]);
			recordBlock = buffer->readBlock(tbName, blockNum);
			for(int j = 0; j < attribute.size(); j++)
			{
				if(attribute[j].attrType < 0)
				{
					int attrPosSize = getAttrPosSize(j, attribute);
					int resInt = recordBlock.readInt((resultRowNum[i]%blockRecordNum) * rowDataSize + attrPosSize);
					stringstream ss;
					ss << resInt;
					string str = ss.str();
					resultStr.push_back(str);
				}
				else if(attribute[j].attrType == 0)
				{
					int attrPosSize = getAttrPosSize(j, attribute);
					float resFloat = recordBlock.readFloat((resultRowNum[i]%blockRecordNum) * rowDataSize + attrPosSize);
					stringstream ss;
					ss << resFloat;
					string str = ss.str();
					resultStr.push_back(str);
				}
				else
				{
					int length = attribute[j].attrType;
					int attrPosSize = getAttrPosSize(j, attribute);
					string resString = recordBlock.readChar((resultRowNum[i]%blockRecordNum) * rowDataSize + attrPosSize, length);
					resultStr.push_back(resString);
				}
			}
			data.push_back(resultStr);
		}
	}
	else
	{
		for(int i = 0; i < attribute.size(); i++)
		{
			for(int j = 0; j < selectCol.size(); j++)
			{
				if(attribute[i].attrName == selectCol[j])
					selectColNum.push_back(i);
			}
		}
		
		for(int i = 0; i < resultRowNum.size(); i++)
		{
			int blockNum = getBlockNum(attribute, resultRowNum[i]);
			recordBlock = buffer->readBlock(tbName, blockNum);
			for(int j = 0; j < selectColNum.size(); j++)
			{
				if(attribute[selectColNum[j]].attrType < 0)
				{
					int attrPosSize = getAttrPosSize(selectColNum[j], attribute);
					int resInt = recordBlock.readInt((resultRowNum[i]%blockRecordNum) * rowDataSize + attrPosSize);
					stringstream ss;
					ss << resInt;
					string str = ss.str();
					resultStr.push_back(str);
				}
				else if(attribute[selectColNum[j]].attrType == 0)
				{
					int attrPosSize = getAttrPosSize(selectColNum[j], attribute);
					float resFloat = recordBlock.readFloat((resultRowNum[i]%blockRecordNum) * rowDataSize + attrPosSize);
					stringstream ss;
					ss << resFloat;
					string str = ss.str();
					resultStr.push_back(str);
				}
				else
				{
					int length = attribute[selectColNum[j]].attrType;
					int attrPosSize = getAttrPosSize(selectColNum[j], attribute);
					string resString = recordBlock.readChar((resultRowNum[i]%blockRecordNum) * rowDataSize + attrPosSize, length);
					resultStr.push_back(resString);
				}
			}
			data.push_back(resultStr);
		}
	}

	return data;

}

vector<vector<string>> Record::select(string tableName, CUserCommand userCommand, vector<Attribute> attribute, vector<int> resultRowNum)
{
	Block recordBlock;
	vector<int> selectRow;
	int rowDataSize(0);
	vector<int> selectColNum;
	vector<vector<int>> rowNum;
	vector<vector<string>> data;
	vector<string> resultStr(NULL);
	vector<string> selectCol = userCommand.GetSelectCol();
	

	string tbName = tableName + ".tb";
	rowDataSize = getRowDataSize(attribute);
	recordBlock = buffer->readBlock(tbName, 0);
	int size = tableName.size();
	int recordcount = recordBlock.readInt(size + 4);
	int blockRecordNum = getBlockRecordNum(attribute);

	/*
	for(int i = 0; i < recordcount; i++)
	{
		resultRow[i] = 0;
	}

	for(int i = 0; i < condition.size(); i++)
	{
		selectRow = index.select(tableName, condition[i]);
		rowNum.push_back(selectRow);   //如果没有对应的数据，需要index返回-1
	}

	for(int i = 0; i < rowNum.size(); i++)
	{
		for(int j = 0; j < rowNum[i].size(); j++)
		{
			int k = rowNum[i][j];
			resultRow[k] += 1;
		}
	}

	for(int i = 0; i < recordcount; i++)
	{
		if(resultRow[i] == size)
			resultRowNum.push_back(i);
	}
	*/
	
	if(selectCol[0] == "*")
	{
		for(int i = 0; i < resultRowNum.size(); i++)
		{
			int blockNum = getBlockNum(attribute, resultRowNum[i]);
			recordBlock = buffer->readBlock(tbName, blockNum);
			for(int j = 0; j < attribute.size(); j++)
			{
				if(attribute[j].attrType < 0)
				{
					int attrPosSize = getAttrPosSize(j, attribute);
					int resInt = recordBlock.readInt((resultRowNum[i]%blockRecordNum) * rowDataSize + attrPosSize);
					stringstream ss;
					ss << resInt;
					string str = ss.str();
					resultStr.push_back(str);
				}
				else if(attribute[j].attrType == 0)
				{
					int attrPosSize = getAttrPosSize(j, attribute);
					float resFloat = recordBlock.readFloat((resultRowNum[i]%blockRecordNum) * rowDataSize + attrPosSize);
					stringstream ss;
					ss << resFloat;
					string str = ss.str();
					resultStr.push_back(str);
				}
				else
				{
					int length = attribute[j].attrType;
					int attrPosSize = getAttrPosSize(j, attribute);
					string resString = recordBlock.readChar((resultRowNum[i]%blockRecordNum) * rowDataSize + attrPosSize, length);
					resultStr.push_back(resString);
				}
			}
			data.push_back(resultStr);
		}
	}
	else
	{
		for(int i = 0; i < attribute.size(); i++)
		{
			for(int j = 0; j < selectCol.size(); j++)
			{
				if(attribute[i].attrName == selectCol[j])
					selectColNum.push_back(i);
			}
		}
		
		for(int i = 0; i < resultRowNum.size(); i++)
		{
			int blockNum = getBlockNum(attribute, resultRowNum[i]);
			recordBlock = buffer->readBlock(tbName, blockNum);
			for(int j = 0; j < selectColNum.size(); j++)
			{
				if(attribute[selectColNum[j]].attrType < 0)
				{
					int attrPosSize = getAttrPosSize(selectColNum[j], attribute);
					int resInt = recordBlock.readInt((resultRowNum[i]%blockRecordNum) * rowDataSize + attrPosSize);
					stringstream ss;
					ss << resInt;
					string str = ss.str();
					resultStr.push_back(str);
				}
				else if(attribute[selectColNum[j]].attrType == 0)
				{
					int attrPosSize = getAttrPosSize(selectColNum[j], attribute);
					float resFloat = recordBlock.readFloat((resultRowNum[i]%blockRecordNum) * rowDataSize + attrPosSize);
					stringstream ss;
					ss << resFloat;
					string str = ss.str();
					resultStr.push_back(str);
				}
				else
				{
					int length = attribute[selectColNum[j]].attrType;
					int attrPosSize = getAttrPosSize(selectColNum[j], attribute);
					string resString = recordBlock.readChar((resultRowNum[i]%blockRecordNum) * rowDataSize + attrPosSize, length);
					resultStr.push_back(resString);
				}
			}
			data.push_back(resultStr);
		}
	}

	return data;
}

vector<int> Record::select(string tableName, vector<Condition> condition, vector<Attribute> attribute)
{
	Block recordBlock;
	string tbName = tableName + ".tb";
	recordBlock = buffer->readBlock(tbName, 0);
	int size = tableName.size();
	int totalRecordCount = recordBlock.readInt(size+4);
	int conSize = condition.size();
	int attrPos;
	bool flag = 0;
	vector<int> resultRowNum;
	vector<vector<string>> data;
	vector<string> resultStr(NULL);
	//vector<string> selectCol = userCommand.GetSelectCol();
	int blockRecordNum = getBlockRecordNum(attribute);
	int rowDataSize = getRowDataSize(attribute);
	vector<int> selectColNum;

	for(int i = 0; i < totalRecordCount; i++)
	{
		for(int j = 0; j < conSize; j++)
		{
			for(int k = 0; k < attribute.size(); k++)
			{
				if(attribute[k].attrName == condition[j].conCol)
					attrPos = k;
				int attrPosSize = getAttrPosSize(k, attribute);
				int blockNum = getBlockNum(attribute, i);
				recordBlock = buffer->readBlock(tbName, blockNum);
				if(attribute[attrPos].attrType < 0)
				{
					int recordValue = recordBlock.readInt((i%blockRecordNum) * rowDataSize + attrPosSize);
					stringstream ss;
					int compareValue;
					ss >> condition[k].conValue;
					ss << compareValue;
					switch(condition[k].conOperator)
					{
						case COMP_EQUAL:		// =
							if(recordValue == compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_NOT_EQUAL:	// <>
							if(recordValue != compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_LESS:			// <
							if(recordValue < compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_LARGE:		// >
							if(recordValue > compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_LESS_EQUAL:	// <=
							if(recordValue <= compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_LARGE_EQUAL:	// >=
							if(recordValue >= compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
					}
				}
				if(attribute[attrPos].attrType == 0)
				{
					float recordValue = recordBlock.readFloat((i%blockRecordNum) * rowDataSize + attrPosSize);
					stringstream ss;
					float compareValue;
					ss >> condition[k].conValue;
					ss << compareValue;
					switch(condition[k].conOperator)
					{
						case COMP_EQUAL:		// =
							if(recordValue == compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_NOT_EQUAL:	// <>
							if(recordValue != compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_LESS:			// <
							if(recordValue < compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_LARGE:		// >
							if(recordValue > compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_LESS_EQUAL:	// <=
							if(recordValue <= compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_LARGE_EQUAL:	// >=
							if(recordValue >= compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
					}
				}
				else
				{
					int length = attribute[attrPos].attrType;
					string recordValue = recordBlock.readChar((i%blockRecordNum) * rowDataSize + attrPosSize, length);
					stringstream ss;
					string compareValue = condition[k].conValue;
					switch(condition[k].conOperator)
					{
						case COMP_EQUAL:		// =
							if(recordValue == compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_NOT_EQUAL:	// <>
							if(recordValue != compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_LESS:			// <
							if(recordValue < compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_LARGE:		// >
							if(recordValue > compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_LESS_EQUAL:	// <=
							if(recordValue <= compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
						case COMP_LARGE_EQUAL:	// >=
							if(recordValue >= compareValue)
								flag = 1;
							else 
								flag = 0;
							break;
					}
				}
			}
		}
		if(flag == 1)
			resultRowNum.push_back(i);
	}
	
	return resultRowNum;
}

void Record::dropTable( string tableName, vector<Attribute> attribute )
{
	string tbName = tableName + ".tb";
	int rowDataSize(0);

	rowDataSize = getRowDataSize(attribute);
	
	Block recordBlock = buffer->readBlock(tbName, 0);
	int size = tableName.size();
	int totalRecordCount = recordBlock.readInt(size + 4);

	int blockNum = getBlockNum(attribute, totalRecordCount);
	
	for(int i = 0; i < blockNum; i++)
	{
		buffer->clearBlock(tbName, i);
	}

	recordBlock = buffer->readBlock(tbName, 0);
	size = tableName.size();
	recordBlock.writeInt(size, 0);
	buffer->writeBlock(tbName, 0, recordBlock);

}


vector<DataLine> Record::deleteRecord(string tableName, vector<int> resultRowNum, vector<Attribute> attribute)
{
	Block recordBlock;
	vector<int> selectRow;
    vector<vector<int>> rowNum;
    string tbName = tableName + ".tb";

	vector<DataLine> result;
	vector<string> resultStr;
	int rowDataSize = getRowDataSize(attribute);
	int blockRecordNum = getBlockRecordNum(attribute);

	//vector<int> resultRowNum = select(tableName, condition, attribute);
	int resultSize = resultRowNum.size();

	if (resultSize > 0)
	{
		/*
		for(i = 0; i < resultRowNum.size(); i++)
		{
		int blockNum = getBlockNum(attribute, resultRowNum[i]);
		if(i != (resultRowNum.size() - 1))
		{
		int blockNumNext = getBlockNum(attribute, resultRowNum[i+1]);
		}
		if(blockNumNext != blockNum)
		{
		recordBlock = buffer.readBlock(tbName, blockNum);
		recordBlock.clear(tbName, (resultRowNum[i]%blockRecordNum) * rowDataSize, rowDataSize);
		buffer.writeBlock(tbName, blockNum, recordBlock);
		}
		else
		{
		recordBlock = buffer.readBlock(tbName, blockNum);
		recordBlock.clear(tbName, (resultRowNum[i]%blockRecordNum) * rowDataSize, rowDataSize);
		}
		}
		*/

		for (int i = 0; i < resultRowNum.size(); i++)
		{
			int blockNum = getBlockNum(attribute, resultRowNum[i]);
			recordBlock = buffer->readBlock(tbName, blockNum);
			recordBlock.writeByte((resultRowNum[i] % blockRecordNum) * rowDataSize, '0');
			for (int j = 0; j < attribute.size(); j++)
			{
				if (attribute[j].attrType < 0)
				{
					int attrPosSize = getAttrPosSize(j, attribute);
					int resInt = recordBlock.readInt((resultRowNum[i] % blockRecordNum) * rowDataSize + attrPosSize);
					stringstream ss;
					ss << resInt;
					string str = ss.str();
					resultStr.push_back(str);
				}
				else if (attribute[j].attrType == 0)
				{
					int attrPosSize = getAttrPosSize(j, attribute);
					float resFloat = recordBlock.readFloat((resultRowNum[i] % blockRecordNum) * rowDataSize + attrPosSize);
					stringstream ss;
					ss << resFloat;
					string str = ss.str();
					resultStr.push_back(str);
				}
				else
				{
					int length = attribute[j].attrType;
					int attrPosSize = getAttrPosSize(j, attribute);
					string resString = recordBlock.readChar((resultRowNum[i] % blockRecordNum) * rowDataSize + attrPosSize, length);
					resultStr.push_back(resString);
				}
			}
			DataLine rowResult;
			rowResult.columns = resultStr;
			rowResult.line = resultRowNum[i];
			result.push_back(rowResult);
		}

		recordBlock = buffer->readBlock(tbName, 0);
		int size = tableName.size();
		int preNum = recordBlock.readInt(size);
		int nowNum = preNum - resultSize;
		recordBlock.writeInt(size, nowNum);
		buffer->writeBlock(tbName, 0, recordBlock);
	}

	return result;

}


int Record::insert(string tableName, vector<string> values, vector<Attribute> attribute)
{
	Block recordBlock;
	string tbName = tableName + ".tb";
	int rowDataSize(0);

	int i;
	int blankRow;
	recordBlock = buffer->readBlock(tbName, 0);
	int size = tableName.size();
	int recordcount = recordBlock.readInt(size + 4);
	rowDataSize = getRowDataSize(attribute);
	int dataSize = recordcount * rowDataSize;
	int blockRecordNum = getBlockRecordNum(attribute);
	int blockNum = getBlockNum(attribute, recordcount);
	if(recordcount!=0 && recordcount%blockRecordNum == 0)
	{
		recordBlock = buffer->readBlock(tbName, blockNum + 1);
	}
	else
	{
		recordBlock = buffer->readBlock(tbName, blockNum);
	}
	
	recordBlock = buffer->readBlock(tbName, 0);
	size = tableName.size();
	int totalRecordCount = recordBlock.readInt(size+4);

	for(i = 0; i < totalRecordCount; i++)
	{
		int blockNum = getBlockNum(attribute, i);
		recordBlock = buffer->readBlock(tbName, blockNum);
		char isWritten = recordBlock.readByte((i%blockRecordNum) * rowDataSize);
		if(isWritten == '0') 
			break;
	}

	if(i == (totalRecordCount - 1))
	{
		char isWritten = recordBlock.readByte((i%blockRecordNum) * rowDataSize);
		if(isWritten == '1') 
			blankRow = i+1;
	}
	else
	{
		blankRow = i;
	}

	for(i = 0; i < attribute.size(); i++)
	{
		if(attribute[i].attrType < 0)
		{
			int value;
			int attrPosSize = getAttrPosSize(i, attribute);
			stringstream ss;
			ss << values[i];
			ss >> value;
			recordBlock.writeInt((blankRow%blockRecordNum) * rowDataSize + attrPosSize, value);
		}
		else if(attribute[i].attrType == 0)
		{
			float value;
			int attrPosSize = getAttrPosSize(i, attribute);
			stringstream ss;
			ss << values[i];
			ss >> value;
			recordBlock.writeFloat((blankRow%blockRecordNum) * rowDataSize + attrPosSize, value);
		}
		else
		{
			int attrPosSize = getAttrPosSize(i, attribute);
			recordBlock.writeChar(values[i], (blankRow%blockRecordNum) * rowDataSize + attrPosSize);
		}
	}

	blockNum = getBlockNum(attribute, blankRow);
	buffer->writeBlock(tbName, blockNum, recordBlock);
			
	recordBlock = buffer->readBlock(tbName, 0);
	size = tableName.size();
	int preNum = recordBlock.readInt(size);
	int preTotalNum = recordBlock.readInt(size+4);
	int nowNum = preNum + 1;
	int nowTotalNum = preTotalNum + 1;
	recordBlock.writeInt(size, nowNum);
	recordBlock.writeInt(size+4, nowTotalNum);
	buffer->writeBlock(tbName, 0, recordBlock);

	return blankRow;
}


/*
int Record::recordCount(string tableName)
{
	for(int i = 0; i < tablerecord.size(); i++)
	{
		if(tablerecord[i].tableName == tableName)
		{
			return tablerecord[i].recordcount;
			break;
		}
	}
}
*/

int Record::getAttrPosSize(int attrPos, vector<Attribute> attribute)
{
	int attrPosSize(0);

	attrPosSize = attrPosSize + 1;

	for(int i = 0; i < attrPos; i++)
	{
		if(attribute[i].attrType <= 0)
		{
			attrPosSize += 4;
		}
		else 
		{
			attrPosSize += attribute[i].attrType;
		}
	}

	return attrPosSize;
}


int Record::getRowDataSize(vector<Attribute> attribute)
{
	int rowDataSize(0);

	rowDataSize = rowDataSize + 1;

	for(int i = 0; i < attribute.size(); i++)
	{
		if(attribute[i].attrType <= 0)
		{
			rowDataSize += 4;
		}
		else 
		{
			rowDataSize += attribute[i].attrType;
		}
	}

	return rowDataSize;
}

int Record::getBlockNum(vector<Attribute> attribute, int rowNum)
{
	int rowDataSize = getRowDataSize(attribute);

	return ((rowNum + 1) * rowDataSize) / BLOCKSIZE + 1; 
}

int Record::getBlockRecordNum(vector<Attribute> attribute)
{
	int rowDataSize = getRowDataSize(attribute);
	int blockRecordNum;

	blockRecordNum = BLOCKSIZE/rowDataSize;

	return blockRecordNum;
}